﻿
using com.iot.core.data;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;
namespace Icom.iot.core.ext
{  
    public static class QueryableExtensions
    {

        //public static IQueryable<TEntity> OrderBy<TEntity>(
        //    this IQueryable<TEntity> source, string orderByProperty,
        //                    bool IsAsc)
        //{
        //    var command = IsAsc ? "OrderBy":"OrderByDescending"  ;
        //    var type = typeof(TEntity);
        //    var property = type.GetProperty(orderByProperty, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
        //    var bChild = orderByProperty.IndexOf(".") > 0;
        //    if (bChild)
        //    {
        //        var arr = orderByProperty.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
        //        property = type.GetProperty(arr[0], BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
        //        type = property.PropertyType;
        //        property = type.GetProperty(arr[1], BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);

        //    }

        //    if (property == null)
        //    {
        //        orderByProperty = "Id";
        //        IsAsc = true;
        //        property = type.GetProperty(orderByProperty, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance); ;
        //    }
        //    var parameter = Expression.Parameter(type, "p");
        //    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
        //    var orderByExpression = Expression.Lambda(propertyAccess, parameter);
        //    var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
        //                                  source.Expression, Expression.Quote(orderByExpression));

        //    return source.Provider.CreateQuery<TEntity>(resultExpression);
        //}

        public static IQueryable<T> ApplySort<T>(this IQueryable<T> source, string sort)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (sort == null)
            {
                return source;
            }

            //把以逗号分隔的排序字符串放数组中
            var listSort = sort.Split(',');

            string completeSortExpression = "";
            foreach (var sortOption in listSort)
            {
                var arr = sortOption.Split(  new char[] { ','},StringSplitOptions.RemoveEmptyEntries); ;
                //如果排序字段以-开头就降序，否则升序
                if (arr.Length > 1 && arr[1]=="desc")
                {
                    completeSortExpression = arr[0] + " descending,";
                }
                else
                {
                    completeSortExpression = arr[0] + ",";
                }
            }

            if (!string.IsNullOrWhiteSpace(completeSortExpression))
            {
                completeSortExpression = completeSortExpression
                    .Remove(completeSortExpression.Count() - 1);
                source = source.OrderBy(completeSortExpression);
            }

            return source;
        }
        public static IQueryable<TEntity> OrderBy<TEntity>(
            this IQueryable<TEntity> source, string orderByProperty,
                   bool IsAsc)
        {
            if (!IsAsc)
            {
                orderByProperty += " descending";
            }
            return source.ApplySort(orderByProperty  );
        }


        public static async Task<List<TEntity>> PageTakeAsync<TEntity>(
           this IQueryable<TEntity> source,
               Page<TEntity> pg

           )
        { 
            var q = source ; 
            var r = await q.Skip((pg.PageNumber - 1) * pg.PageSize)
               .Take(pg.PageSize)
               .ToListAsync();
            return r;
        } 
        public static async Task<List<TEntity>> SortPageTakeAsync<TEntity>(
            this IQueryable<TEntity> source,  
                Sort sort,
                Page<TEntity> pg
            
            )
        {
            var orderByProperty = sort.Filed;
            if (!sort.Asc)
            {
                orderByProperty += " descending";
            }
            var q=source.ApplySort(orderByProperty);
            return await q.PageTakeAsync( pg); 
        }

        public static   List<TEntity> PageTake<TEntity>(
           this IQueryable<TEntity> source,
               Page<TEntity> pg

           )
        {
            var q = source;
            var r =   q.Skip((pg.PageNumber - 1) * pg.PageSize)
               .Take(pg.PageSize)
               .ToList();
            return r;
        }
        public static   List<TEntity> SortPageTake<TEntity>(
            this IQueryable<TEntity> source,
                Sort sort,
                Page<TEntity> pg

            )
        {
            var orderByProperty = sort.Filed;
            if (!sort.Asc)
            {
                orderByProperty += " descending";
            }
            var q = source.ApplySort(orderByProperty);
            return   q.PageTake(pg);
        }



    }
}
